﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Devmil.MVVM.Dependencies
{
    public class NotifyDependencyNode
    {
        public WeakReference GetterSenderObject { get; private set; }
        public WeakReference GetterTargetObject { get; private set; }
        public string PropertyName { get; private set; }

        public bool IsAlive
        {
            get
            {
                return (GetterSenderObject == null || GetterSenderObject.IsAlive) && (GetterTargetObject == null || GetterTargetObject.IsAlive);
            }
        }

        public NotifyDependencyNode(object getterSenderObject, object getterTargetObject, string propertyName)
        {
            GetterSenderObject = getterSenderObject == null ? null : new WeakReference(getterSenderObject);
            GetterTargetObject = getterTargetObject == null ? null : new WeakReference(getterTargetObject);
            PropertyName = propertyName;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is NotifyDependencyNode))
                return false;
            NotifyDependencyNode castedObj = (NotifyDependencyNode)obj;
            if ((GetterSenderObject == null) != (castedObj.GetterSenderObject == null))
                return false;
            if (GetterSenderObject != null && GetterSenderObject.IsAlive != castedObj.GetterSenderObject.IsAlive)
                return false;
            if (GetterSenderObject != null && GetterSenderObject.IsAlive && !object.ReferenceEquals(GetterSenderObject.Target, castedObj.GetterSenderObject.Target))
                return false;
            
            if ((GetterTargetObject == null) != (castedObj.GetterTargetObject == null))
                return false;
            if (GetterTargetObject != null && GetterTargetObject.IsAlive != castedObj.GetterTargetObject.IsAlive)
                return false;
            if (GetterTargetObject != null && GetterTargetObject.IsAlive && !object.ReferenceEquals(GetterTargetObject.Target, castedObj.GetterTargetObject.Target))
                return false;
            
            if (!string.Equals(PropertyName, castedObj.PropertyName))
                return false;

            return true;
        }

        public override int GetHashCode()
        {
            int result = 0;
            if (GetterSenderObject != null)
                result ^= GetterSenderObject.GetHashCode();
            if (GetterTargetObject != null) 
                result ^= GetterTargetObject.GetHashCode();
            if (PropertyName != null)
                result ^= PropertyName.GetHashCode();
            return result;
        }
    }
}
